package com.my.utils;

import com.my.redis.pojo.KeyValue;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.util.Assert;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Created by 80002023 on 2016/6/13.
 */
public class CommonUtils {

    private final static Logger logger = LogManager.getLogger(CommonUtils.class);

    private final static Class<String> STRING_CLASS = String.class;

    /**
     * @param str
     * @return
     */
    public static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        return pattern.matcher(str).matches();
    }

    /**
     * @param target
     * @return
     */
    public static List<KeyValue> readPropertyAndValue(Object target) {
        Assert.notNull(target, "Source must not be null");

        List<KeyValue> keyValues = new ArrayList<KeyValue>();

        Class actualEditable = target.getClass();

        PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
        for (PropertyDescriptor pd : targetPds) {

            Method getter = pd.getReadMethod();
            try {
                Object value = getter.invoke(target);
                logger.info("property name:{}, value:{}", pd.getName(), value);
                if (value != null) {
                    keyValues.add(new KeyValue(pd.getName(), value.toString()));
                }
            } catch (IllegalAccessException e) {
//                e.printStackTrace();
                logger.error("{} property get value Access failed!", pd.getName());
            } catch (InvocationTargetException e) {
//                e.printStackTrace();
                logger.error("{} property get value InvocationTarget failed!", pd.getName());
            }

        }
        return keyValues;
    }

    public static PropertyDescriptor[] getPropertyDescriptors(Class<?> clazz) throws BeansException {

        Field[] fields = clazz.getDeclaredFields();
        Method[] methods = clazz.getDeclaredMethods();
        logger.info("class name:{}, field length:{}, method length:{}", clazz.getName(), fields.length, methods.length);

        List<PropertyDescriptor> propertyDescriptors = new ArrayList<PropertyDescriptor>();
        for (Field field : fields) {
            logger.info("field name:{}, type:{}", field.getName(), field.getType());
            if (field.getType().isInterface()) {
                continue;
            }
            try {
                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), clazz);
                propertyDescriptors.add(propertyDescriptor);
            } catch (IntrospectionException e) {
//                e.printStackTrace();
                logger.error("{} new PropertyDescriptor failed!", field.getName());
            }
        }
        return propertyDescriptors.toArray(new PropertyDescriptor[]{});
    }

    public static boolean isNotEmpty(String str) {
        return StringUtils.isNotEmpty(str);
    }

    public static KeyValue getKey(List<KeyValue> records, String id) {
        for (KeyValue record : records) {
            if (isEquals(record.getKey(), id)) {
                return record;
            }
        }
        return null;
    }

    private static boolean isEquals(Object a, Object b) {
        if (a == null || b == null) {
            return false;
        }
        if (STRING_CLASS.isInstance(a) && STRING_CLASS.isInstance(b)) {
            return a.equals(b);
        }
        return false;
    }
}
